home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 365 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  5.5 KB

  1. Path: fido.asd.sgi.com!austern
  2. From: gregor@netcom.com (Greg Colvin)
  3. Newsgroups: comp.std.c++
  4. Subject: auto_ptr idioms
  5. Date: 08 Feb 1996 10:10:20 PST
  6. Organization: Netcom Online Communications Services (408-241-9760 login: guest)
  7. Approved: austern@isolde.mti.sgi.com
  8. Message-ID: <gregorDMG2B0.5vw@netcom.com>
  9. NNTP-Posting-Host: isolde.mti.sgi.com
  10. X-Original-Date: Thu, 8 Feb 1996 06:35:24 GMT
  11. Apparently-To: comp-std-c++@uunet.uu.net
  12. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  13.     iQBVAwUBMRo8oUy4NqrwXLNJAQFsuwH+IThah/4FrTesgjmjWk6jmM3RN9SoJqBg
  14.     vVx2wNZLplzIY9xGY0Vy41fmUf7LWcStyEu2VX1y9LpoyMdYREWfOw==
  15.     =eDcn
  16. Originator: austern@isolde.mti.sgi.com
  17.  
  18. Many of the comments I have received on auto_ptr seem to be based on a
  19. desire to be able to use an auto_ptr "just like an ordinary pointer".
  20. I share this desire, but I did not design auto_ptr to satisfy it.  My
  21. gc_ptr and counted_ptr proposals came much closer, but did not satisfy
  22. the committee.  Rather, auto_ptr was designed to provide exception safety in
  23. just three very restricted idioms.  I hope a little motivation and history
  24. will clarify the issues, and perhaps convince you of the need for the changes
  25. I am proposing.
  26.  
  27. The fundamental problem for exception safety was fixing code like this:
  28.    void g(T*);
  29.    void f() {
  30.       T* p(new T);
  31.       g(p);
  32.       delete p;
  33.    }
  34. If the function g() throws an exception then delete p will not be called.
  35. Of course you could write this instead:
  36.    void g(T*);
  37.    void f() {
  38.       T* p(new T);
  39.       try {
  40.          g(p);
  41.       } catch(...) {
  42.          delete p;
  43.          throw;
  44.       }
  45.       delete p;
  46.    }
  47. But would you want to?  Not me.  The auto_ptr template provides a simpler
  48. "resource acquistion is initialization" idiom:
  49.    void g(T*);
  50.    void f() {
  51.       auto_ptr<T> p(new T);
  52.       g(&*p);
  53.    }
  54. All that auto_ptr was absolutely *required* to do is support this idiom, and
  55. that is all my original auto_ptr proposal did.  In this it was like earlier
  56. sugestions by John Skaller and Steve Rumbsy.  However, Bill Gibbons of
  57. Taligent reported: that Taligent had considerable experience with a class
  58. much like auto_ptr, that they found that a copy semantics essential, and
  59. that the appropriate semantics was to transfer ownership.
  60.  
  61. Given a copy semantics, two other useful idioms become possible:
  62.  
  63.    // sink() is responsible for deleting its argument
  64.    void sink(auto_ptr<T>);
  65.  
  66.    // source() returns a pointer that its caller is responsible for deleting
  67.    auto_ptr<T> source();
  68.  
  69. Given careful use of auto_ptr (no calls to get(), reset(), or release()) the
  70. sink() function is sure to delete its argument, and the caller of source() is
  71. sure to delete its returned pointer.  So far so good.
  72.  
  73. Unfortunately, the current semantics of C++ do not allow the following:
  74.    auto_ptr<T> p(source());
  75. This is because the copy semantics for auto_ptr are destructive (non-const),
  76. but passing the value returned by source() to the copy constructor requires
  77. a temporary, which cannot be passed to auto_ptr(auto_ptr&) for reasons that
  78. remain obscure to me (and to all the compilers I own), but that are spelled
  79. out in the ARM (8.4.3).
  80.  
  81. To fix the source() idiom I propose to make the auto_ptr copy semantics
  82. non-destructive.  Currently, when you copy an auto_ptr the source ends up
  83. holding a null pointer.  I propose instead to leave the source pointer
  84. unchanged, but transfer ownership of the object pointed to.  Arguably, a
  85. change in ownership is not a change in the state of any particular auto_ptr,
  86. and no public function will tell you which auto_ptr owns a particular pointer,
  87. so the copy constructor and assignment operator are "logically" const, and we
  88. can use mutable state to implement them with const arguments.
  89.  
  90. Note that this change does not affect the three idioms above at all: you
  91. would write the same code after the change as you would now.  Still, the
  92. change is not for free.  Some criticisms and my response follow.
  93.  
  94. Performance.  A little more space and time will be needed to represent the
  95. pointer value and the object ownership separately.
  96.    True, but the cost is small even for portable implementations, and can be
  97.    made even smaller in non-portable ones.  I think the cost is worth it.
  98.  
  99. Safety.  Now, an auto_ptr cannot be a dangling pointer, although it can be
  100. null.  With this change a non-null auto_ptr might be a dangling pointer.
  101.    True, but this is not a problem for the idioms auto_ptr is designed to
  102.    support.  The problem was to be sure that pointers held in automatic
  103.    variables are deleted when exceptions are thrown, not to prevent dangling
  104.    pointers.  Regardless, dereferencing a null pointer is no less undefined
  105.    than dereferencing a dangling pointer, and the available memory utilities
  106.    like Purify, BoundsChecker, and Great Circle will handle either case
  107.    equally well.
  108.  
  109. Convenience.  Now, I can use get() to test whether an auto_ptr is still
  110. valid.  With this change I cannot.
  111.    True, but again not a problem for the above idioms.  In my opinion, the
  112.    effective use of auto_ptr requires careful design.  Questions like whether
  113.    an auto_ptr is an owner or is valid must be answerable statically, by
  114.    design, any attempt to answer them at runtime will be fraught with peril.
  115.    If you really need to answer these questions at runtime then you need
  116.    some form of reference counting or tracing garbage collection.
  117. ---
  118. [ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  119.   Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy is
  120.   in http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]
  121.